#include "GameSystem.hpp"
#include "IGameComponent.hpp"
#include <algorithm>

using namespace Typhoon;

GameSystem::GameSystem() {
	ID = IDCounter++;
}

GameSystem::~GameSystem() {

}

void GameSystem::AddGameObject(GameObject* gameObject) {
	if (!gameObject->SatisfyAspect(aspect)) return;
	gameObjects.push_back(gameObject);
	gameObject->ComponentRemoved += event_handler(this, &GameSystem::ComponentRemoved);
	gameObject->RemovedFromWorld += event_handler(this, &GameSystem::GameObjectRemovedFromWorld);
	GameObjectAdded(gameObject);
}

void GameSystem::RemoveGameObject(GameObject* gameObject) {
	GameObjects::iterator it = std::find(gameObjects.begin(), gameObjects.end(), gameObject);
	if (it==gameObjects.end()) return;
	gameObject->ComponentRemoved -= event_handler(this, &GameSystem::ComponentRemoved);
	gameObject->RemovedFromWorld -= event_handler(this, &GameSystem::GameObjectRemovedFromWorld);
	gameObjects.erase(it);
	GameObjectRemoved(gameObject);
}

void GameSystem::GameObjectAdded(GameObject* gameObject) {}
void GameSystem::GameObjectRemoved(GameObject* gameObject) {}

GameSystem::GameObjects& GameSystem::GetGameObjects() {
	return gameObjects;
}

int GameSystem::IDCounter = 0;

void GameSystem::AddData(IGameComponent* component, void* data) {
	component->AddData(ID, data);
}

void* GameSystem::GetData(IGameComponent* component) {
	return component->GetData(ID);
}

GameSystem::SubSystems& GameSystem::GetSubSystems() {
	return subSystems;
}

void GameSystem::ComponentRemoved(GameObject* gameObject) {
	if (gameObject->SatisfyAspect(aspect)) return;
	RemoveGameObject(gameObject);
}

void GameSystem::GameObjectRemovedFromWorld(GameObject* gameObject) {
	RemoveGameObject(gameObject);
}

void GameSystem::Remove() {
	GameObjects temp = gameObjects;
	for (GameObjects::iterator it = temp.begin(); it!=temp.end(); ++it) {
		RemoveGameObject(*it);
	}
}

bool GameSystem::ContainsGameObject(GameObject* gameObject) {
	GameObjects::iterator it = std::find(gameObjects.begin(), gameObjects.end(), gameObject);
	return (it!=gameObjects.end());
}